package com.gcloud.mesh.redis;

import com.gcloud.mesh.asset.enums.MockType;
import com.gcloud.mesh.header.exception.BaseException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service("MockRedis")
public class MockRedis<T> {

	@Autowired
	private RedisTemplate<String, T> redisTemplate;

	public void setBeginTime(T obj) {
		String key = RedisKeyConsts.RedisKey.SYS_BEGIN_TIME;
		BoundValueOperations<String, T> valueOperations = redisTemplate.boundValueOps(key);
		valueOperations.set(obj);
	}
	
	public Long getBeginTime() {
		String key = RedisKeyConsts.RedisKey.SYS_BEGIN_TIME;
		Long res = (Long) redisTemplate.opsForValue().get(key);
		return res;
	}
	
	public T getValue(String key){
		T res = redisTemplate.opsForValue().get(key);
		return res;
	}
	
	public void setValue(String key, T obj){
		BoundValueOperations<String, T> valueOperations = redisTemplate.boundValueOps(key);
		valueOperations.set(obj);
	}
	
	public void updateTimeout(String key, Long expireDate) {
		redisTemplate.expire(key, expireDate, TimeUnit.SECONDS);
	}
	
	public void updateHoursTimeout(String key, Long expireDate) {
		redisTemplate.expire(key, expireDate, TimeUnit.HOURS);
	}
	
	public List<T> getUserToken(){
		String key = MessageFormat.format(RedisKeyConsts.RedisKey.SYS_USER_TOKEN, "*");
		Set<String> keys = redisTemplate.keys(key);
		
		List<T> res = new ArrayList<>();

		if (keys != null && keys.size() > 0) {
			for (String k : keys) {
				BoundValueOperations<String, T> valueOperations = redisTemplate.boundValueOps(k);
				T obj = valueOperations.get();
				if (obj != null) {
					res.add(obj);
				}
			}
		}
		return res;
	}
	
	public void setResponseTime(T obj) {
		String key = RedisKeyConsts.RedisKey.SYS_SERVICE_RESPONSE_TIME;
		BoundValueOperations<String, T> valueOperations = redisTemplate.boundValueOps(key);
		valueOperations.set(obj);
	}
	
	public Long getResponseTime() {
		String key = RedisKeyConsts.RedisKey.SYS_SERVICE_RESPONSE_TIME;
		Long res = (Long) redisTemplate.opsForValue().get(key);
		return res;
	}
	
	public void set(String id, MockType type, T obj) {
		String key = MessageFormat.format(RedisKeyConsts.RedisKey.MOCK_DATA_TYPE_ID, type.getType(), id);
		BoundValueOperations<String, T> valueOperations = redisTemplate.boundValueOps(key);
		valueOperations.set(obj);

	}

	public void setMonitorData(String meter, String resourceId, T value) {
		String key = MessageFormat.format(RedisKeyConsts.RedisKey.MONITOR_DATA, meter, resourceId);
		BoundValueOperations<String, T> valueOperations = redisTemplate.boundValueOps(key);
		valueOperations.set(value);
		if (redisTemplate.getExpire(key, TimeUnit.SECONDS) <= 0) {
			redisTemplate.expire(key, 300, TimeUnit.SECONDS);
		}
	}

	public List<T> getByTypeAndId(MockType type, String id) {
		String key = MessageFormat.format(RedisKeyConsts.RedisKey.MOCK_DATA_TYPE_ID, type.getType(), id);

		Set<String> keys = redisTemplate.keys(key);

		List<T> res = new ArrayList<>();

		if (keys != null && keys.size() > 0) {
			for (String k : keys) {
				BoundValueOperations<String, T> valueOperations = redisTemplate.boundValueOps(k);
				T obj = valueOperations.get();
				if (obj != null) {
					res.add(obj);
				}
			}
		}
		return res;
	}

	public List<T> getByType(MockType type) {
		String key = MessageFormat.format(RedisKeyConsts.RedisKey.MOCK_DATA_TYPE_SEARCH, type.getType());

		Set<String> keys = redisTemplate.keys(key);

		List<T> res = new ArrayList<>();

		if (keys != null && keys.size() > 0) {
			for (String k : keys) {
				BoundValueOperations<String, T> valueOperations = redisTemplate.boundValueOps(k);
				T obj = valueOperations.get();
				if (obj != null) {
					res.add(obj);
				}
			}
		}
		return res;
	}
	
	public List<T> getByType(String key) {

		Set<String> keys = redisTemplate.keys(key);

		List<T> res = new ArrayList<>();

		if (keys != null && keys.size() > 0) {
			for (String k : keys) {
				BoundValueOperations<String, T> valueOperations = redisTemplate.boundValueOps(k);
				T obj = valueOperations.get();
				if (obj != null) {
					res.add(obj);
				}
			}
		}
		return res;
	}

	public String getMonitorData(String meter, String resourceId) {
		String key = MessageFormat.format(RedisKeyConsts.RedisKey.MONITOR_DATA, meter, resourceId);

		String res = (String) redisTemplate.opsForValue().get(key);

		return res;
	}

	public Map<String, String> getMonitorDataByType(String meter) {
		Map<String, String> res = new HashMap<String, String>();

		String allKey = MessageFormat.format(RedisKeyConsts.RedisKey.MONITOR_DATA, meter, "*");

		Set<String> keys = redisTemplate.keys(allKey);

		for (String key : keys) {
			String resourceId = key.replaceAll(MessageFormat.format(RedisKeyConsts.RedisKey.MONITOR_DATA, meter, ""), "").trim();
			res.put(resourceId, (String) redisTemplate.opsForValue().get(key));
		}
		return res;
	}

	/**
	 * 
	 * @Title: remove
	 * @Description: TODO
	 * 
	 * @param ruleId
	 * @throws GCloudException
	 */
	public void delete(String id, MockType type) throws BaseException {
		String key = MessageFormat.format(RedisKeyConsts.RedisKey.MOCK_DATA_TYPE_ID, id, type.getType());
		Set<String> keys = redisTemplate.keys(key);
		if (keys != null && keys.size() > 0) {
			for (String k : keys) {
				redisTemplate.delete(k);
			}
		}
	}
	
	public void delete(String key) throws BaseException {
		Set<String> keys = redisTemplate.keys(key);
		if (keys != null && keys.size() > 0) {
			for (String k : keys) {
				redisTemplate.delete(k);
			}
		}
	}

}
